// ProbePCAVisualizerEditor.cs
// Custom Editor for ProbePCAVisualizer: UI overlay, average error, direction buttons, probe selection
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;

[CustomEditor(typeof(GPUProbePCAVisualizer))]
public class GPUProbePCAVisualizerEditor : Editor
{
    GPUProbePCAVisualizer vis;

    void OnEnable() => vis = (GPUProbePCAVisualizer)target;

    public override void OnInspectorGUI()
    {
        if (target == null)
        {
            return;
        }

        serializedObject.Update();

        UnityLightProbeOption();

        EditorGUILayout.Space();
        
        PCALightProbeOption();
        
        EditorGUILayout.Space();
        
        VisualObject();
        
        EditorGUILayout.Space();

        VisualObjectToggle();

        EditorGUILayout.Space();
        
        ErrorStatistics();
        
        SceneView.RepaintAll();
        serializedObject.ApplyModifiedProperties();
    }

    private void UnityLightProbeOption()
    {
        GUILayout.Label("原始光照探针生成", new GUIStyle(EditorStyles.boldLabel));

        SerializedProperty serializedLightProbeGroup = serializedObject.FindProperty("lightProbeGroup");
        SerializedProperty lightProbeCountInGroup = serializedObject.FindProperty("lightProbeCountInGroup");
        
        EditorGUILayout.PropertyField(serializedLightProbeGroup);
        EditorGUILayout.PropertyField(lightProbeCountInGroup);
        
        if (GUILayout.Button("生成LightProbe"))
        {
            LightProbeGroup lightProbeGroup = (LightProbeGroup)serializedLightProbeGroup.boxedValue;
            if (lightProbeGroup == null)
            {
                return;
            }

            int count = lightProbeCountInGroup.intValue;
            Vector3[] pos = new Vector3[count * count * count];

            int index = 0;
            for (int x = 0; x < count; x++)
            {
                for (int y = 0; y < count; y++)
                {
                    for (int z = 0; z < count; z++)
                    {
                        pos[index++] = new Vector3(x, y, z);
                    }
                }
            }

            lightProbeGroup.probePositions = pos;
        }
    }

    private void PCALightProbeOption()
    {
        GUILayout.Label("PCA Compress Settings(需要先烘培LightProbe)", EditorStyles.boldLabel);
        
        SerializedProperty serializedCompressedProbeData = serializedObject.FindProperty("compressedProbeData");
        EditorGUILayout.PropertyField(serializedCompressedProbeData);
        
        SerializedProperty serializedPCAMethod = serializedObject.FindProperty("pcaMethod");
        SerializedProperty serializedPCACmponents = serializedObject.FindProperty("pcaCmponents");
        
        serializedPCAMethod.boxedValue = (PCAUtils.PrincipalAxisMethod)EditorGUILayout.EnumPopup("主轴提取方法", ((PCAUtils.PrincipalAxisMethod)serializedPCAMethod.boxedValue));
        serializedPCACmponents.intValue =  EditorGUILayout.IntSlider("主轴数量", serializedPCACmponents.intValue, 1, 27);
        
        if (GUILayout.Button("Compress and Save"))
        {
            CompressedProbeData compressedProbeData = PCAUtils.CompressProbe(serializedPCACmponents.intValue, (PCAUtils.PrincipalAxisMethod)serializedPCAMethod.boxedValue);
            
            PCAUtils.SaveData(compressedProbeData);    
        }
    }
    
    private void VisualObject()
    {
        GUILayout.Label("根据LightProbe生成可视化对象", new GUIStyle(EditorStyles.boldLabel));
        
        SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;

        SerializedProperty serializedVisualGOTemp = serializedObject.FindProperty("visualGOTemp");
        GameObject visualGOTemp = serializedVisualGOTemp.boxedValue as GameObject;
        
        EditorGUILayout.PropertyField(serializedVisualGORoot);
        EditorGUILayout.PropertyField(serializedVisualGOTemp);
        
        if (GUILayout.Button("生成可视化对象"))
        {
            SerializedProperty serializedLightProbeGroup = serializedObject.FindProperty("lightProbeGroup");
            LightProbeGroup lightProbeGroup = (LightProbeGroup)serializedLightProbeGroup.boxedValue;
            
            // for (int i = 0; i < visualGORoot.transform.childCount;)
            // {
            //     GameObject.Destroy(vis.transform.GetChild(i));
            // }
            
            for (int i = 0; i < lightProbeGroup.probePositions.Length; i++)
            {
                GameObject go = GameObject.Instantiate(visualGOTemp, visualGORoot.transform, true);
                go.transform.localPosition = lightProbeGroup.probePositions[i];
                go.transform.localRotation = Quaternion.identity;
                go.transform.localScale = Vector3.one;

                lightProbeGroup.probePositions[i] = visualGORoot.transform.localPosition;
            }
        }
    }
    
    private void VisualObjectToggle()
    {
        GUILayout.Label("可视化显示", new GUIStyle(EditorStyles.boldLabel));
        
        SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;
        
        SerializedProperty serializedSampleDirection = serializedObject.FindProperty("sampleDirection");
        SerializedProperty serializedChannel = serializedObject.FindProperty("channel");
        
        EditorGUILayout.PropertyField(serializedSampleDirection);
        EditorGUILayout.PropertyField(serializedChannel);
        
        //Unity 的采样方法 
        // EditorGUILayout.BeginHorizontal();
        
        // if (GUILayout.Button("Show Unity Light Probe Full （Unity Function）"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateSHL2(LightmapSettings.lightProbes.bakedProbes[i], vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         // mrs[i].material.color = col;
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        
        // if (GUILayout.Button("Show Compress Light Probe Full （Unity Function）"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateSHL2(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        
        EditorGUILayout.BeginHorizontal();
        
        if (GUILayout.Button("Show Unity Light Probe Full"))
        {
            MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
            for (int i = 0; i < mrs.Length; i++)
            {
                var col = SHUtility.EvaluateFullV(LightmapSettings.lightProbes.bakedProbes[i], vis.GetSampleDirection());
                //col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
                
                MaterialPropertyBlock mpb = new MaterialPropertyBlock();
                mpb.SetFloat("_ByCompress", 0);
                // if (col.r < 0)
                // {
                //     mpb.SetVector("_BaseColor", new Color(1,0,0,1));    
                // }
                // else
                {
                    mpb.SetVector("_BaseColor", col);    
                }
                
                mrs[i].SetPropertyBlock(mpb);
            }
        }
        
        if (GUILayout.Button("Show Compress Light Probe Full (C#)"))
        {
            MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
            for (int i = 0; i < mrs.Length; i++)
            {
                var col = SHUtility.EvaluateFullV(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
                //col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
                // float a = vis.compressedProbeData.mean[1];
                // col = new Color(a, a, a, a);
                //
                // Vector4 v = Vector4.one;
                // if (a < 0)
                // {
                //     v = Color.red;
                // }
                //
                //
                // if (i < 27)
                // {
                //     float b = vis.compressedProbeData.mean[i];
                //     v = new Vector4(b, b, b, b) * 100;
                // }
                //
                // v =  new Vector4( vis.compressedProbeData.coefficients[i,0], vis.compressedProbeData.coefficients[i,1], vis.compressedProbeData.coefficients[i,2],1);

                // col = new Vector4(vis.compressedProbeData.coefficients[i, 1],
                //     vis.compressedProbeData.coefficients[i, 2], vis.compressedProbeData.coefficients[i, 3], 1);
                
                MaterialPropertyBlock mpb = new MaterialPropertyBlock();
                mpb.SetFloat("_ByCompress", 0);
                mpb.SetVector("_BaseColor", col);
                mrs[i].SetPropertyBlock(mpb);
            }
        }
        
        if (GUILayout.Button("Show Compress Light Probe Full (Shader)"))
        {
            MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
            for (int i = 0; i < mrs.Length; i++)
            {
                // var col = SHUtility.EvaluateFull(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
                // col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
                 
                MaterialPropertyBlock mpb = new MaterialPropertyBlock();
                mpb.SetFloat("_ByCompress", 1);
                mpb.SetFloat("_LightProbeIdx", i);
                mrs[i].SetPropertyBlock(mpb);
            }
        }
        
        EditorGUILayout.EndHorizontal();

        // EditorGUILayout.BeginHorizontal();
        //
        // if (GUILayout.Button("Show Unity Light Probe L0L1"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL0L1(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // if (GUILayout.Button("Show Compress Light Probe L0L1"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL0L1(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        //
        // if (GUILayout.Button("Show Unity Light Probe L0"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL0(LightmapSettings.lightProbes.bakedProbes[i]);
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // if (GUILayout.Button("Show Compress Light Probe L0"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL0(vis.DecodeSH(vis.compressedProbeData, i));
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        //
        // if (GUILayout.Button("Show Unity Light Probe L1"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL1(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // if (GUILayout.Button("Show Compress Light Probe L1"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL1(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        //
        // if (GUILayout.Button("Show Unity Light Probe L2"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL2(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // if (GUILayout.Button("Show Compress Light Probe L2"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var col = SHUtility.EvaluateL2(vis.DecodeSH(vis.compressedProbeData, i), vis.GetSampleDirection());
        //         col = ProbePCAVisualizer.FilterChannel(col, vis.channel);
        //         
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor", col);
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        // if (GUILayout.Button("纯白色"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor",  new Color(1,1,1));
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        //
        // if (GUILayout.Button("纯黑色"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        //         mpb.SetColor("_BaseColor",  new Color(0,0,0));
        //         mrs[i].SetPropertyBlock(mpb);
        //     }
        // }
        // EditorGUILayout.EndHorizontal();
        //
        // if (GUILayout.Button("Clear Color & MaterialPropertyBlock"))
        // {
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         mrs[i].SetPropertyBlock(null);
        //     }
        // }
    }

    private float errorL0;
    private float errorL1;
    private float errorL0L1;
    private float errorL2;
    private float errorAll;
    private int errorAmplify = 1;
    private void ErrorStatistics()
    {
        // GUILayout.Label("误差计算", new GUIStyle(EditorStyles.boldLabel));
        //
        // EditorGUILayout.PropertyField(serializedObject.FindProperty("originalSHs"));
        // EditorGUILayout.PropertyField(serializedObject.FindProperty("decodedSHs"));
        // EditorGUILayout.PropertyField(serializedObject.FindProperty("errors"));
        // errorAmplify =  EditorGUILayout.IntSlider("误差可视化系数", errorAmplify, 1, 20);
        // EditorGUILayout.BeginHorizontal();
        //
        // EditorGUILayout.LabelField("整体平均误差值：" + errorAll);
        //
        // if (GUILayout.Button("重新计算"))
        // {
        //     var baked = LightmapSettings.lightProbes.bakedProbes;
        //     int n = vis.compressedProbeData.positions.Length;
        //     
        //     vis.originalSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.decodedSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.errors = new float[n];
        //     for (int i = 0; i < n; i++)
        //     {
        //         vis.originalSHs[i] = baked[i];
        //         vis.decodedSHs[i] = vis.DecodeSH(vis.compressedProbeData, i);
        //         // error magnitude
        //         var oC = SHUtility.EvaluateFull(vis.originalSHs[i], vis.GetSampleDirection());
        //         var dC = SHUtility.EvaluateFull(vis.decodedSHs[i],  vis.GetSampleDirection());
        //         vis.errors[i] = ProbePCAVisualizer.ComputeError(oC,dC);
        //     }
        //     
        //     float sum = 0f;
        //     foreach (var e in vis.errors) sum += e;
        //     errorAll = sum / vis.errors.Length;
        // }
        //
        // if (GUILayout.Button("可视化显示"))
        // {
        //     SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        //     GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var original = SHUtility.EvaluateFull(vis.originalSHs[i], vis.GetSampleDirection());
        //         var decoded = SHUtility.EvaluateFull(vis.decodedSHs[i],  vis.GetSampleDirection());
        //         float error = ProbePCAVisualizer.ComputeError(original,decoded);
        //         
        //         float t = Mathf.Clamp01(error * errorAmplify);
        //         mrs[i].material.color = Color.Lerp(Color.green, Color.red, t);;
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        //
        // EditorGUILayout.LabelField("L0L1平均误差值：" + errorL0L1);
        //
        // if (GUILayout.Button("重新计算"))
        // {
        //     var baked = LightmapSettings.lightProbes.bakedProbes;
        //     int n = vis.compressedProbeData.positions.Length;
        //     
        //     vis.originalSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.decodedSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.errors = new float[n];
        //     for (int i = 0; i < n; i++)
        //     {
        //         vis.originalSHs[i] = baked[i];
        //         vis.decodedSHs[i] = vis.DecodeSH(vis.compressedProbeData, i);
        //         // error magnitude
        //         var oC = SHUtility.EvaluateL0L1(vis.originalSHs[i], vis.GetSampleDirection());
        //         var dC = SHUtility.EvaluateL0L1(vis.decodedSHs[i],  vis.GetSampleDirection());
        //         vis.errors[i] = ProbePCAVisualizer.ComputeError(oC,dC);
        //     }
        //     
        //     float sum = 0f;
        //     foreach (var e in vis.errors) sum += e;
        //     errorL0L1 = sum / vis.errors.Length;
        // }
        //
        // if (GUILayout.Button("可视化显示"))
        // {
        //     SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        //     GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var original = SHUtility.EvaluateL0L1(vis.originalSHs[i], vis.GetSampleDirection());
        //         var decoded = SHUtility.EvaluateL0L1(vis.decodedSHs[i],  vis.GetSampleDirection());
        //         
        //         float error = ProbePCAVisualizer.ComputeError(original,decoded);
        //         
        //         float t = Mathf.Clamp01(error * errorAmplify);
        //         mrs[i].material.color = Color.Lerp(Color.green, Color.red, t);;
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        // EditorGUILayout.LabelField("L0平均误差值：" + errorL0);
        //
        // if (GUILayout.Button("重新计算"))
        // {
        //     var baked = LightmapSettings.lightProbes.bakedProbes;
        //     int n = vis.compressedProbeData.positions.Length;
        //     
        //     vis.originalSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.decodedSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.errors = new float[n];
        //     for (int i = 0; i < n; i++)
        //     {
        //         vis.originalSHs[i] = baked[i];
        //         vis.decodedSHs[i] = vis.DecodeSH(vis.compressedProbeData, i);
        //         // error magnitude
        //         var oC = SHUtility.EvaluateL0(vis.originalSHs[i]);
        //         var dC = SHUtility.EvaluateL0(vis.decodedSHs[i]);
        //         vis.errors[i] = ProbePCAVisualizer.ComputeError(oC,dC);
        //     }
        //     
        //     float sum = 0f;
        //     foreach (var e in vis.errors) sum += e;
        //     errorL0 = sum / vis.errors.Length;
        // }
        //
        // if (GUILayout.Button("可视化显示"))
        // {
        //     SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        //     GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var original = SHUtility.EvaluateL0(vis.originalSHs[i]);
        //         var decoded = SHUtility.EvaluateL0(vis.decodedSHs[i]);
        //         
        //         float error = ProbePCAVisualizer.ComputeError(original,decoded);
        //         
        //         float t = Mathf.Clamp01(error * errorAmplify);
        //         mrs[i].material.color = Color.Lerp(Color.green, Color.red, t);;
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        // EditorGUILayout.LabelField("L1平均误差值：" + errorL1);
        // if (GUILayout.Button("重新计算"))
        // {
        //     var baked = LightmapSettings.lightProbes.bakedProbes;
        //     int n = vis.compressedProbeData.positions.Length;
        //     
        //     vis.originalSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.decodedSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.errors = new float[n];
        //     for (int i = 0; i < n; i++)
        //     {
        //         vis.originalSHs[i] = baked[i];
        //         vis.decodedSHs[i] = vis.DecodeSH(vis.compressedProbeData, i);
        //         // error magnitude
        //         var oC = SHUtility.EvaluateL1(vis.originalSHs[i],vis.GetSampleDirection());
        //         var dC = SHUtility.EvaluateL1(vis.decodedSHs[i], vis.GetSampleDirection());
        //         vis.errors[i] = ProbePCAVisualizer.ComputeError(oC,dC);
        //     }
        //     
        //     float sum = 0f;
        //     foreach (var e in vis.errors) sum += e;
        //     errorL1 = sum / vis.errors.Length;
        // }
        //
        // if (GUILayout.Button("可视化显示"))
        // {
        //     SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        //     GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var original = SHUtility.EvaluateL1(vis.originalSHs[i], vis.GetSampleDirection());
        //         var decoded = SHUtility.EvaluateL1(vis.decodedSHs[i],  vis.GetSampleDirection());
        //         
        //         float error = ProbePCAVisualizer.ComputeError(original,decoded);
        //         
        //         float t = Mathf.Clamp01(error * errorAmplify);
        //         mrs[i].material.color = Color.Lerp(Color.green, Color.red, t);;
        //     }
        // }
        //
        // EditorGUILayout.EndHorizontal();
        //
        // EditorGUILayout.BeginHorizontal();
        // EditorGUILayout.LabelField("L2平均误差值：" + errorL2);
        // if (GUILayout.Button("重新计算"))
        // {
        //     var baked = LightmapSettings.lightProbes.bakedProbes;
        //     int n = vis.compressedProbeData.positions.Length;
        //     
        //     vis.originalSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.decodedSHs = new SphericalHarmonicsL2[baked.Length];
        //     vis.errors = new float[n];
        //     for (int i = 0; i < n; i++)
        //     {
        //         vis.originalSHs[i] = baked[i];
        //         vis.decodedSHs[i] = vis.DecodeSH(vis.compressedProbeData, i);
        //         
        //         var oC = SHUtility.EvaluateL2(vis.originalSHs[i],vis.GetSampleDirection());
        //         var dC = SHUtility.EvaluateL2(vis.decodedSHs[i], vis.GetSampleDirection());
        //         vis.errors[i] = ProbePCAVisualizer.ComputeError(oC,dC);
        //     }
        //     
        //     float sum = 0f;
        //     foreach (var e in vis.errors) sum += e;
        //     errorL2 = sum / vis.errors.Length;
        // }
        // if (GUILayout.Button("可视化显示"))
        // {
        //     SerializedProperty serializedVisualGORoot = serializedObject.FindProperty("visualGORoot");
        //     GameObject visualGORoot = serializedVisualGORoot.boxedValue as GameObject;
        //     MeshRenderer[] mrs = visualGORoot.GetComponentsInChildren<MeshRenderer>();
        //     for (int i = 0; i < mrs.Length; i++)
        //     {
        //         var original = SHUtility.EvaluateL2(vis.originalSHs[i], vis.GetSampleDirection());
        //         var decoded = SHUtility.EvaluateL2(vis.decodedSHs[i],  vis.GetSampleDirection());
        //         
        //         float error = ProbePCAVisualizer.ComputeError(original,decoded);
        //         
        //         float t = Mathf.Clamp01(error * errorAmplify);
        //         mrs[i].material.color = Color.Lerp(Color.green, Color.red, t);;
        //     }
        // }
        // EditorGUILayout.EndHorizontal();
    }
    
    void OnSceneGUI()
    {
        Event e = Event.current;
        if (e.type == EventType.MouseDown && e.button == 0)
        {
            Ray ray = HandleUtility.GUIPointToWorldRay(e.mousePosition);
            if (Physics.Raycast(ray, out var hit))
            {
                // find nearest probe index
                float minD = float.MaxValue;
                int idx = -1;
                for (int i = 0; i < vis.positions.Length; i++)
                {
                    float d = (vis.positions[i] - hit.point).sqrMagnitude;
                    if (d < minD) { minD = d; idx = i; }
                }
                vis.selectedProbe = idx;
                SceneView.RepaintAll();
            }
        }
    }
}